import core.util.HashMap;
import core.util.Listeners;

class xcms.DataBus
{
    /**
     * Initializes the data bus.
     */
    this.DataBus = function() {
        this.consumers = new core.util.HashMap();
    }

    /**
     * Subscribes the given consumer to the specified event. Note that subscribe/publish mechanism
     * used to communicate objects with each other. DataBus is a mediator between
     * the publisher and the subscriber.
     *
     * @param eventName (string) Unique event name started with 'on' (e.g. onCmsInin or onAuthComplete)
     * @param consumer (object) Event consumer object.
     */
    this.subscribe = function( eventName, consumer )
    {
        if( !this.consumers.hasKey( eventName ) )
        {
            this.consumers.set( eventName, new core.util.Listeners() );
        }
        this.consumers.get( eventName ).add( consumer );
    }

    /**
     * Unsubscribes the given consumer from the event.
     *
     * @param eventName (string)  Unique event name started with 'on' (e.g. onCmsInin or onAuthComplete)
     * @param consumer (object) Event consumer object.
     */
    this.unsubscribe = function( eventName, consumer )
    {
        if( this.consumers.hasKey( eventName ) )
        {
            this.consumers.get( eventName ).remove( consumer );
        }
    }

    /**
     * Publishes new event with the given name to the subscribers.
     *
     * @param event (string) Event name started with 'on' (e.g. onCmsInit).
     * @param args (array) [optional] Arguments to be passed to consumer's method.
     */
    this.publish = function( eventName, args )
    {
        console.debug( 'Publishing event ' + eventName + ' with arguments ' + args );
        if( this.consumers.hasKey( eventName ) )
        {
            this.consumers.get( eventName ).call( eventName, args );
        }
    }
}

/**
 * @return DataBus singleton instance.
 */
xcms.DataBus.get = function()
{
    if( !defined( this.instance ) )
    {
        this.instance = new DataBus();
    }
    return this.instance;
}

/**
 * Package built-in function.
 *
 * @param eventName Name of the event to publsh.
 * @param args Arguments to be passed to consumer's method.
 */
xcms.publish = function( eventName, args )
{
    DataBus.get().publish( eventName, args );
}

/**
 * Package built-in function.
 *
 * @param eventName Name of the event to subscribe.
 * @param subscriber Subscriber object.
 * @see DataBus.subscribe
 */
xcms.subscribe = function( eventName, subscriber )
{
    DataBus.get().subscribe( eventName, subscriber );
}

/**
 * Package built-in function.
 *
 * @param eventName Name of the event to unsubscribe.
 * @param subscriber Subscriber object.
 * @see DataBus.unsubscribe
 */
xcms.unsubscribe = function( eventName, subscriber )
{
    DataBus.get().unsubscribe( eventName, subscriber );
}